//
//  testdominion.c
//  dominion
//
//  Created by Doug Mason on 2/16/14.
//  Copyright (c) 2014 Doug Mason. All rights reserved.
//

#include "testdominion.h"
 int rand_range(int min, int max)
{
    return ((rand() % (max-min+1)) + min);
}

void testDiscard(int p, struct gameState *postState,int trash){
    struct gameState preState;
    int failed_tests = 0;
    srand(time(NULL));
    memcpy(&preState,postState,sizeof(struct gameState));
    int result;
    int preCount = postState->handCount[p];
    int prePlayed = postState->playedCardCount;
    int preDiscard= postState->discardCount[p];
    printf("Number of cards in hand for player %i is %i: \n",p,postState->handCount[p]);
    //test drawing first card for player 1, trashing and incrementing played count
    result = discardCard(p,0,postState,trash);
    if(result !=0){
        printf("Failure in discard for the first card for player %i\n",p);
        failed_tests+=1;
    }
    if(preCount-1!=postState->handCount[p]){
        printf("Failure to decrement card amount following discard for player %d.\n",p);
        failed_tests+=1;
    }
    if(trash==0){
        if(postState->discardCount[p]!=(preDiscard+1)){
            printf("failed to increment discard pile when trash flag is disabled");
            failed_tests+=1;
        }
    }
    printf("Number of failed tests for testDiscard for this run: %d ",failed_tests);
}


void testGainCard(struct gameState* state, int player){
    int result;
    int failed_tests = 0;
    result = gainCard(smithy,state,2,player);
    if(result!=0 || state->handCount[player]<=5){
        printf("Failed test for adding a card to the hand for player %i\n",player);
        failed_tests+=1;
    }
    result = gainCard(sea_hag,state,2,player);
    if(result==0){
        printf("Failed on adding a card that is not in play!");
        failed_tests+=1;
    }

    result = gainCard(remodel,state,0,player);
    int preDiscard = state->discardCount[player];

    if(result!=0 || state->discardCount[player] == preDiscard){
        printf("Test failed for discarding card for player %i \n.",player);
        failed_tests+=1;
    }

    result = gainCard(baron,state,1,player);
    int preDeckCount = state->deckCount[player];
    if(result !=0 || state->deckCount[player]==preDeckCount){
        printf("Failed test for incrementing deck count for player %i. \n",player);
        failed_tests+=1;
    }

    if(failed_tests==0){
        printf("All tests passed for testGainCard.\n");
    }
    else{
        printf("Number of tests failed for testGainCard %i .\n",failed_tests);
    }
}

void testEndTurn(struct gameState *state,int player){
    int result,failed_tests=0;
    result = endTurn(state);
    int turn = whoseTurn(state);
    if(result !=0 || turn == player){
        printf("failed to change turn for %i\n",player);
        failed_tests+=1;
    }
    else{
        int newPlayer = whoseTurn(state);
        if(state->handCount[player]!=0){
            printf("Failed to discard hand for player %i\n",player);
            failed_tests+=1;
        }
        if(state->phase !=0){
            printf("Failed to reset game phase\n");
            failed_tests+=1;
        }
        if(state->handCount[newPlayer] !=5){
            printf("Failed to draw 5 cards for next player\n");
            failed_tests+=1;
        }
        if(state->numActions !=1){
            printf("Failed to reset number of actions\n");
            failed_tests+=1;
        }
        if(state->coins!=0){
            printf("Failed to reset coins for player %i\n",turn);
            failed_tests+=1;
        }
        if(state->numBuys!=1){
            printf("Failed to reset buys for player %i\n",turn);
            failed_tests+=1;
        }
        if(state->playedCardCount!=0){
            printf("Failed to reset played card count for player %i\n",turn);
            failed_tests+=1;
        }

    }
    if(failed_tests==0){
        printf("All tests for endTurn passed\n");
    }
    else{
        printf("Number of failed tests for endTurn %i for player %i \n",failed_tests,player);
    }
}


void testNumHandCards(struct gameState* state){
    int failed_tests = 0;
    int result = numHandCards(state);
    //testing initial number of cards
    if(result !=5){
        printf("Failed test for getting initial number of cards for current player\n");
        failed_tests+=1;
    }

}

void playDominion(struct gameState* G){
    int money = 0;
    int smithyPos = -1;
    int adventurerPos = -1;
    int i=0;
    int numSmithies = 0;
    int numAdventurers = 0;
    int buyResult = 0;
    printSupply(G);
    while (!isGameOver(G)) {
        printf("Player %d beginning, resetting turn state and printing current player's hand.\n",whoseTurn(G));
        money = 0;
        smithyPos = -1;
        adventurerPos = -1;
        int badPlayCardTestResult;
        printHand(whoseTurn(G),G);
        printf("determining money as well as effect cards for smithy or adventurer.");
        for (i = 0; i < numHandCards(G); i++) {
            if (handCard(i, G) == copper)
                money++;
            else if (handCard(i, G) == silver)
                money += 2;
            else if (handCard(i, G) == gold)
                money += 3;
            else if (handCard(i, G) == smithy){
                printf("Smithy is in the player's hand at postion %d",i);
                smithyPos = i;}
            else if (handCard(i, G) == adventurer){
                printf("Adventurer is in the player's hand at postion %d",i);
                adventurerPos = i;
            }
        }
        if (smithyPos != -1) {
            printf("%d: smithy played from position %d\n",whoseTurn(G), smithyPos);
            testPlayCard(smithyPos, -1, -1, -1, G);
            printf("smithy played.\n");
            money = 0;
            i=0;
            while(i<numHandCards(G)){
                if (handCard(i, G) == copper){
                    printf("Playing copper\n");
                    testPlayCard(i, -1, -1, -1, G);
                    money++;
                }
                else if (handCard(i, G) == silver){
                    printf("Playing silver\n");
                    testPlayCard(i, -1, -1, -1, G);
                    money += 2;
                }
                else if (handCard(i, G) == gold){
                    printf("Playing Gold.\n");
                    testPlayCard(i, -1, -1, -1, G);
                    money += 3;
                }
                i++;
            }
        }
        testUpdateCoins(whoseTurn(G),G,0);
        if (G->coins >= 8) {
            printf("%d: bought province\n",whoseTurn(G));
            buyCard(province, G);

        }
        else if ((G->coins >= 6) && (numAdventurers < 2) && (supplyCount(adventurer, G) >=1)) {
            printf("1: bought adventurer\n");
            buyCard(adventurer, G);
            numAdventurers++;
        }

        else if (G->coins >= 6) {
            printf("%d: bought gold\n",whoseTurn(G));
            buyCard(gold, G);
        }
        else if (G->coins  >= 5 && (supplyCount(council_room,G) >=1)) {
            printf("%d: bought council_room\n",whoseTurn(G));
            buyCard(council_room, G);
        }
        else if (G->coins  >= 5 && (supplyCount(mine,G) >=1)) {
            printf("%d: bought council_room\n",whoseTurn(G));
            buyCard(mine, G);
        }
        else if (G->coins  >= 5 && (supplyCount(tribute,G) >=1)) {
            printf("%d: bought tribute\n",whoseTurn(G));
            buyCard(tribute, G);
        }
        else if (G->coins  >= 5 && (supplyCount(minion,G) >=1)) {
            printf("%d: bought minion\n",whoseTurn(G));
            buyCard(minion, G);
        }
        else if ((G->coins  >= 4) && (numSmithies < 2) && (supplyCount(smithy, G)>=1)) {
            printf("%d: bought smithy\n",whoseTurn(G));
            buyCard(smithy, G);
            numSmithies++;
        }
        else if ((G->coins  >= 4) && (supplyCount(baron, G)>=1)) {
            printf("%d: bought baron\n",whoseTurn(G));
            buyCard(baron, G);
        }
        else if ((G->coins  >= 4) && (supplyCount(salvager, G)>=1)) {
            if(G->supplyCount[salvager]!=-1){
            printf("%d: bought salvager\n",whoseTurn(G));
            buyCard(salvager, G);
            }else{

            }
        }
        else if ((G->coins  >= 4) && (supplyCount(cutpurse, G)>=1)) {
            printf("%d: bought cutpurse\n",whoseTurn(G));
            buyCard(cutpurse, G);
        }
        else if ((G->coins  >= 4) && (supplyCount(sea_hag, G)>=1)) {
            printf("%d: bought sea hag\n",whoseTurn(G));
            buyCard(sea_hag, G);
        }
        else if((G->coins >=4)&&supplyCount(gardens,G)>=1){
            printf("%d: bought gardens\n",whoseTurn(G));
            buyCard(gardens, G);
        }
        else if((G->coins >=4)&&supplyCount(feast,G)>=1){
            printf("%d: bought feast\n",whoseTurn(G));
            buyCard(feast, G);
        }
        else if((G->coins >=4)&&supplyCount(remodel,G)>=1){
            printf("%d: bought remodel\n",whoseTurn(G));
            buyCard(remodel, G);
        }
        else if((G->coins >=4)&&supplyCount(treasure_map,G)>=1){
            printf("%d: bought treasure map\n",whoseTurn(G));
            buyCard(treasure_map, G);
        }
        else if ((G->coins  >= 3)  && supplyCount(steward, G)>=1) {
            printf("%d: bought steward\n",whoseTurn(G));
            buyCard(steward, G);
        }
        else if ((G->coins  >= 3)  && supplyCount(village, G)>=1) {
            printf("%d: bought village\n",whoseTurn(G));
            buyCard(steward, G);
        }

        else if ((G->coins  >= 3)  && supplyCount(great_hall, G)>=1) {
            printf("%d: bought great_hall\n",whoseTurn(G));
            buyCard(great_hall, G);
        }

        else if ((G->coins  >= 3)  && supplyCount(ambassador, G)>=1) {
            printf("%d: bought ambassador\n",whoseTurn(G));
            buyCard(ambassador, G);
        }
        else if (G->coins  >= 3) {
            printf("%d: bought silver\n",whoseTurn(G));
            buyCard(silver, G);
        }
        else{
            int cointoss = rand_range(0,250);
            if(cointoss > 15){
                printf("%d: bought copper\n",whoseTurn(G));
                buyCard(copper, G);
            }
            else{
                
                printf("%d: bought curse\n",whoseTurn(G));
                buyCard(curse, G);
                
            }
        }
        
        while(G->numActions>0&&G->handCount[whoseTurn(G)]!=0){
            printf("cards in hand: %i\n",G->handCount[whoseTurn(G)]);
            int idx = rand()%5;
            int cardtobuy= 0;
            int cardtoplay = G->hand[whoseTurn(G)][idx];
            if(cardtoplay >=adventurer && cardtoplay <=treasure_map){
                while(cardtobuy==0){
                    int testcard = rand_range(adventurer,treasure_map);
                    if(G->supplyCount[testcard]>0){
                        cardtobuy = testcard;
                    }
                }
                
                testPlayCard(idx,cardtobuy,0,0,G);
                int randAction = rand()%5;
                if(randAction==0){
                    //this should fail
                     badPlayCardTestResult =testPlayCard(idx,gold,0,0,G);
                    assert(badPlayCardTestResult==-1);
                }
            }
            G->numActions--;
            
        }
        printf("%d: end turn\n",whoseTurn(G));
        endTurn(G);

    } // end of Game Loop

}

int numTreasure(struct gameState* state){
    int player = whoseTurn(state);
    int results = 0;
    int i;
    for(i = 0; i < state->handCount[player];i++){
        if(state->hand[player][i] == gold || state->hand[player][i] == silver || state->hand[player][i] == copper){
            results++;
        }
    }
    return results;
}


int testPlayCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state)
{
    int card;
    int coin_bonus = 0; 		//tracks coins gain from actions

    //check if it is the right phase
    if (state->phase != 0)
    {
        printf("State is not in the correct phase to play the current card attempted\n");
        return -1;
    }

    //check if player has enough actions
    if ( state->numActions < 1 )
    {
        printf("Player did not have an action available\n");
        return -1;
    }

    //get card played
    card = handCard(handPos, state);
	//card = state->hand[whoseTurn(state)][handPos];
    //check if selected card is an action
    if ( card < adventurer || card > treasure_map )
    {
        printf("Card is not an action\n");
        return -1;
    }
	int card_result = 0;
    //play card
    switch (card) {
        case adventurer:
            testAdventurer(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case great_hall:
            testGreatHall(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
        case salvager:
            testSalvager(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case outpost:
            testOutpost(handPos,state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case steward:
            testSteward(state,whoseTurn(state));
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case council_room:
            testCouncilRoom(state);
            break;
        case village:
            testVillage(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case remodel:
            testRemodel(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case feast:
            testFeast(state);
            printf("Discarding played card.\n");
            
            break;
        case minion:
            testMinion(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case baron:
            testBaron(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        case sea_hag:
            testSeaHag(state);
            printf("Discarding played card.\n");
            testDiscard(handPos,state,0);
            break;
        default:
//            card_result =cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus);
//            printf("Discarding played card.\n");
//            testDiscard(handPos,state,0);
            break;
    }

    if (  card_result< 0 )
    {
        printf("Card effect was not played correctly!");
        return -1;
    }

    //reduce number of actions
    state->numActions--;

    //update coins (Treasure cards may be added with card draws)
    updateCoins(state->whoseTurn, state, coin_bonus);

    return 0;
}

int main (int argc, char** argv) {
    srand(time(NULL));

//        struct gameState* G = newGame();
    int resources[10];
    int *res;
    int games;
    int initResult = 0;
    for (games = 0; games < 500; games++) {
        struct gameState *G = newGame();
        int numPlayers = (rand()%4)+2;
        srand(time(NULL));
        if(numPlayers > 4){
            numPlayers-=2;
        }
        printf ("Starting game %d with %d players.\n",games,numPlayers);
        printf("Selecting set of Kingdom cards.");

        selectKingdomCards(random()%RAND_MAX,resources);
        res=
        kingdomCards(resources[0],resources[1],resources[2],resources[3],resources[4],resources[5],resources[6],resources[7],resources[8],resources[9]);

        printf("Kingdom cards: %i %i %i %i %i %i %i %i %i %i",resources[0],resources[1],resources[2],resources[3],resources[4],resources[5],resources[6],resources[7],resources[8],resources[9]);
        initResult = testInitializeGame(numPlayers, res, rand(), G);
        if(initResult == -1){
          continue;
        }
        printSupply(G);
        playDominion(G);
        printf ("Finished game %d.\n",games);

        int whom;
        for (whom = 0; whom < numPlayers; whom++) {
            printf("Player %d: %d\n",whom,scoreFor(whom,G));
        }
        int players[4];
        testGetWinners(players,G);
        memset((void*)resources,0,10*sizeof(int));
        printf("Resetting game.");
        memset ((void*)G, 0, sizeof(struct gameState));
    }


    return 0;
}
